﻿package fj.ui
{
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.ui.Mouse;
	
	import fj.events.FJImageTransformScaleEvent;
	import fj.events.FJImageTransformMoveEvent;
	import fj.events.FJImageTransformRotateEvent;

	public class FJImageTransformSelector extends MovieClip
	{
		public var ui:MovieClip;
		public var handlers:MovieClip;
		
		private var angleOffset:Number;
		private var angleTempOffset:Number;

		private var originalWidth:Number;
		private var originalHeight:Number;
		private var scaleOffset:Number;

		private var xOffset:Number;
		private var yOffset:Number;

		private var isUI:Boolean;
		private var isDown:Boolean;
		private var isOver:Boolean;
		private var type:String;

		private var _mouseScale:MovieClip;
		private var _mouseRotate:MovieClip;

		public function FJImageTransformSelector():void
		{
			_mouseScale = getChildByName( "mouse_scale" ) as MovieClip;
			_mouseRotate = getChildByName( "mouse_rotate" ) as MovieClip;
			_mouseScale.visible = false;
			_mouseRotate.visible = false;

			isUI = true;

			for ( var i:int = 1; i<=4; i++ ) {
				var tempRotateHandler:MovieClip = handlers.getChildByName( "rotate_"+i ) as MovieClip;
				tempRotateHandler.addEventListener( MouseEvent.MOUSE_DOWN, rotateDown );
				tempRotateHandler.addEventListener( MouseEvent.MOUSE_OVER, rotateOver );
				tempRotateHandler.addEventListener( MouseEvent.MOUSE_OUT, rotateOut );
				var tempScaleHandler:MovieClip = handlers.getChildByName( "scale_"+i ) as MovieClip;
				tempScaleHandler.addEventListener( MouseEvent.MOUSE_DOWN, scaleDown );
				tempScaleHandler.addEventListener( MouseEvent.MOUSE_OVER, scaleOver );
				tempScaleHandler.addEventListener( MouseEvent.MOUSE_OUT, scaleOut );
			}
			handlers.alpha = 0;
			handlers.move.addEventListener( MouseEvent.MOUSE_DOWN, moveDown );
			addEventListener( Event.ENTER_FRAME, cursorLoop );
		}
		public function adjust( w:Number, h:Number ):void
		{
			angleOffset = 0;
			var dx:Number = w/2;
			var dy:Number = h/2;
			scaleOffset = Math.sqrt( dx*dx+dy*dy );
			area.width = w;
			area.height = h;
			ui.adjust(w,h);
			handlers.adjust( w, h );
			originalWidth = w;
			originalHeight = h;
		}
		public function show():void
		{
			ui.visible = true;
			isUI = true;
		}
		public function hide():void
		{
			ui.visible = false;
			isUI = false;
		}
		private function rotateDown( e:MouseEvent ):void
		{
			if ( isUI ) {
				type = "rotate";
				isDown = true;
				angleTempOffset = Math.atan2( mouseY, mouseX )*180/Math.PI;
				stage.addEventListener( MouseEvent.MOUSE_MOVE, onRotate );
				stage.addEventListener( MouseEvent.MOUSE_UP, onUp );
			}
		}
		private function rotateOver( e:MouseEvent ):void
		{
			if ( isUI ) {
				Mouse.hide();
				if ( !isDown ) {
					_mouseRotate.visible = true;
				}
				isOver = true;
			}
		}
		private function rotateOut( e:MouseEvent ):void
		{
			if ( !isDown ) {
				Mouse.show();
				_mouseRotate.visible = false;
			}
			isOver = false;
		}
		private function scaleDown( e:MouseEvent ):void
		{
			if ( isUI ) {
				type = "scale";
				isDown = true;
				stage.addEventListener( MouseEvent.MOUSE_MOVE,onScale );
				stage.addEventListener( MouseEvent.MOUSE_UP, onUp );
			}
		}
		private function scaleOver( e:MouseEvent ):void
		{
			if ( isUI ) {
				Mouse.hide();
				if ( !isDown ) {
					_mouseScale.visible = true;
					_mouseScale.rotation = area.rotation;
					if( area.mouseX < 0 ){
						if( area.mouseY <0 ){
							_mouseScale.scaleX = 1;
						} else {
							_mouseScale.scaleX = -1;
						}
					} else {
						if( area.mouseY <0 ){
							_mouseScale.scaleX = -1;
						} else {
							_mouseScale.scaleX = 1;
						}
					}
				}
				isOver = true;
			}
		}
		private function scaleOut( e:MouseEvent ):void
		{
			if ( !isDown ) {
				Mouse.show();
				_mouseScale.visible = false;
			}
			isOver = false;
		}
		private function moveDown( e:MouseEvent ):void
		{
			type = "move";
			xOffset = mouseX;
			yOffset = mouseY;
			stage.addEventListener( MouseEvent.MOUSE_MOVE, onMove );
			stage.addEventListener( MouseEvent.MOUSE_UP, onUp );
		}
		private function onUp( e:MouseEvent ):void
		{
			switch ( type ) {
				case "rotate" :
					angleOffset = ui.rotation;
					if ( !isOver ) {
						_mouseRotate.visible = false;
					}
					stage.removeEventListener( MouseEvent.MOUSE_MOVE, onRotate );
					break;
				case "scale" :
					if ( !isOver ) {
						_mouseScale.visible = false;
					}
					stage.removeEventListener( MouseEvent.MOUSE_MOVE, onScale );
					break;
				case "move" :
					xOffset = x;
					yOffset = y;
					stage.removeEventListener( MouseEvent.MOUSE_MOVE, onMove );
					break;
			}
			if ( !isOver ) {
				Mouse.show();
			}
			isDown = false;
			
			stage.removeEventListener( MouseEvent.MOUSE_UP, onUp );
		}
		private function onRotate( e:MouseEvent ):void
		{
			area.rotation = Math.atan2( mouseY, mouseX )*180/Math.PI - angleTempOffset + angleOffset;
			ui.rotation = handlers.rotation = area.rotation;
			dispatchEvent( new FJImageTransformRotateEvent( area.rotation ) );
		}
		private function onScale( e:MouseEvent ):void
		{
			area.scaleX = area.scaleY = Math.sqrt( mouseX*mouseX+mouseY*mouseY )/scaleOffset;
			ui.rotation = handlers.rotation = 0;
			ui.adjust(originalWidth*area.scaleX,originalHeight*area.scaleY);
			handlers.adjust(originalWidth*area.scaleX,originalHeight*area.scaleY);
			ui.rotation = handlers.rotation = area.rotation;
			dispatchEvent( new FJImageTransformScaleEvent( area.scaleX ) );
		}
		private function onMove( e:MouseEvent ):void
		{
			x = parent.mouseX - xOffset;
			y = parent.mouseY - yOffset;

			dispatchEvent( new FJImageTransformMoveEvent( x, y ) );
		}
		private function cursorLoop( e:Event ):void
		{
			_mouseRotate.x = mouseX;
			_mouseRotate.y = mouseY;
			_mouseScale.x = mouseX;
			_mouseScale.y = mouseY;
		}
	}
}